home *** CD-ROM | disk | FTP | other *** search
- ; Program to illustrate high-speed text-drawing operation of
- ; write mode 3 of the VGA.
- ; Draws a string of 8x14 characters at arbitrary locations
- ; without disturbing the background, using VGA's 8x14 ROM font.
- ; Designed for use with modes 0Dh, 0Eh, 0Fh, 10h, and 12h.
- ; Runs only on VGAs (in Models 50 & up and IBM Display Adapter
- ; and 100% compatibles).
- ; Assembled with MASM 4.0, linked with LINK 3.51.
- ; By Michael Abrash, 9/1/87.
- ; Page 22, Volume 6.1 Programmer's Journal
- ;
- stack segment para stack 'STACK'
- db 512 dup(?)
- stack ends
- ;
- VGA_VIDEO_SEGMENT equ 0a000h ;VGA display memory segment
- SCREEN_WIDTH_IN_BYTES equ 044ah ;offset of BIOS variable
- FONT_CHARACTER_SIZE equ 14 ;# bytes in each font char
- ;
- ; VGA register equates.
- ;
- SC_INDEX equ 3c4h ;SC index register
- SC_MAP_MASK equ 2 ;SC map mask register index
- GC_INDEX equ 3ceh ;GC index register
- GC_SET_RESET equ 0 ;GC set/reset register index
- GC_ENABLE_SET_RESET equ 1 ;GC enable set/reset register index
- GC_ROTATE equ 3 ;GC data rotate/logical function
- ; register index
- GC_MODE equ 5 ;GC Mode register
- GC_BIT_MASK equ 8 ;GC bit mask register index
- ;
- dseg segment para common 'DATA'
- TEST_TEXT_ROW equ 69 ;row to display test text at
- TEST_TEXT_COL equ 17 ;column to display test text at
- TEST_TEXT_COLOR equ 0fh ;high intensity white
- TestString label byte
- db 'Hello, world!',0 ;test string to print.
- FontPointer dd ? ;font offset
- dseg ends
- ;
- cseg segment para public 'CODE'
- assume cs:cseg, ds:dseg
- start proc near
- mov ax,dseg
- mov ds,ax
- ;
- ; Select 640x480 graphics mode.
- ;
- mov ax,012h
- int 10h
- ;
- ; Set the screen to all blue, using the readability of VGA registers
- ; to preserve reserved bits.
- ;
- mov dx,GC_INDEX
- mov al,GC_SET_RESET
- out dx,al
- inc dx
- in al,dx
- and al,0f0h
- or al,1 ;blue plane only set, others reset
- out dx,al
- dec dx
- mov al,GC_ENABLE_SET_RESET
- out dx,al
- inc dx
- in al,dx
- and al,0f0h
- or al,0fh ;enable set/reset for all planes
- out dx,al
- mov dx,VGA_VIDEO_SEGMENT
- mov es,dx ;point to display memory
- mov di,0
- mov cx,8000h ;fill all 32k words
- mov ax,0ffffh ;because of set/reset, the value
- ; written actually doesn't matter
- rep stosw ;fill with blue
- ;
- ; Set driver to use the 8x14 font.
- ;
- mov ah,11h ;VGA BIOS character generator function,
- mov al,30h ; return info subfunction
- mov bh,2 ;get 8x14 font pointer
- int 10h
- call SelectFont
- ;
- ; Print the test string.
- ;
- mov si,offset TestString
- mov bx,TEST_TEXT_ROW
- mov cx,TEST_TEXT_COL
- mov ah,TEST_TEXT_COLOR
- call DrawString
- ;
- ; Wait for a key, then set to text mode & end.
- ;
- mov ah,1
- int 21h ;wait for a key
- mov ax,3
- int 10h ;restore text mode
- ;
- ; Exit to DOS.
- ;
- mov ah,4ch
- int 21h
- Start endp
- ;
- ; Subroutine to draw a text string left-to-right in a linear
- ; graphics mode (0Dh, 0Eh, 0Fh, 010h, 012h) with 8-dot-wide
- ; characters. Background around the pixels that make up the
- ; characters is preserved.
- ; Font used should be pointed to by FontPointer.
- ;
- ; Input:
- ; AH = color to draw string in
- ; BX = row to draw string on
- ; CX = column to start string at
- ; DS:SI = string to draw
- ;
- ; Forces ALU function to "move".
- ; Forces write mode 3.
- ;
- DrawString proc near
- push ax
- push bx
- push cx
- push dx
- push si
- push di
- push bp
- push ds
- ;
- ; Set up set/reset to produce character color, using the readability
- ; of VGA register to preserve the setting of reserved bits 7-4.
- ;
- mov dx,GC_INDEX
- mov al,GC_SET_RESET
- out dx,al
- inc dx
- in al,dx
- and al,0f0h
- and ah,0fh
- or al,ah
- out dx,al
- ;
- ; Select write mode 3, using the readability of VGA registers
- ; to leave bits other than the write mode bits unchanged.
- ;
- mov dx,GC_INDEX
- mov al,GC_MODE
- out dx,al
- inc dx
- in al,dx
- or al,3
- out dx,al
- mov dx,VGA_VIDEO_SEGMENT
- mov es,dx ;point to display memory
- ;
- ; Calculate screen address of byte character starts in.
- ;
- push ds ;point to BIOS data segment
- sub dx,dx
- mov ds,dx
- mov di,ds:[SCREEN_WIDTH_IN_BYTES] ;retrieve BIOS
- ; screen width
- pop ds
- mov ax,bx ;row
- mul di ;calculate offset of start of row
- push di ;set aside screen width
- mov di,cx ;set aside the column
- and cl,0111b ;keep only the column in-byte address
- shr di,1
- shr di,1
- shr di,1 ;divide column by 8 to make a byte address
- add di,ax ;and point to byte
- ;
- ; Set up the GC rotation. In write mode 3, this is the rotation
- ; of CPU data before it is ANDed with the Bit Mask register to
- ; form the bit mask. Force the ALU function to "move". Uses the
- ; readability of VGA registers to leave reserved bits unchanged.
- ;
- mov dx,GC_INDEX
- mov al,GC_ROTATE
- out dx,al
- inc dx
- in al,dx
- and al,0e0h
- or al,cl
- out dx,al
- ;
- ; Set up BH as bit mask for left half, BL as rotation for right half.
- ;
- mov bx,0ffffh
- shr bh,cl
- neg cl
- add cl,8
- shl bl,cl
- ;
- ; Draw all characters, left portion first, then right portion in the
- ; succeeding byte, using the data rotation to position the character
- ; across the byte boundary and then using write mode 3 to combine the
- ; character data with the bit mask to allow the set/reset value (the
- ; character color) through only for the proper portion (where the
- ; font bits for the character are 1) of the character for each byte.
- ; Wherever the font bits for the character are 0, the background
- ; color is preserved.
- ; Does not check for case where character is byte-aligned and
- ; no rotation and only one write is required.
- ;
- ; Draw the left portion of each character in the string.
- ;
- pop cx ;get back screen width
- push si
- push di
- push bx
- ;
- ; Set the bit mask for the left half of the character.
- ;
- mov dx,GC_INDEX
- mov al,GC_BIT_MASK
- mov ah,bh
- out dx,ax
- LeftHalfLoop:
- lodsb
- and al,al
- jz LeftHalfLoopDone
- call CharacterUp
- inc di ;point to next character location
- jmp LeftHalfLoop
- LeftHalfLoopDone:
- pop bx
- pop di
- pop si
- ;
- ; Draw the right portion of each character in the string.
- ;
- inc di ;right portion of each character is across
- ; byte boundary
- ;
- ; Set the bit mask for the right half of the character.
- ;
- mov dx,GC_INDEX
- mov al,GC_BIT_MASK
- mov ah,bl
- out dx,ax
- RightHalfLoop:
- lodsb
- and al,al
- jz RightHalfLoopDone
- call CharacterUp
- inc di ;point to next character location
- jmp RightHalfLoop
- RightHalfLoopDone:
- ;
- pop ds
- pop bp
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- DrawString endp
- ;
- ; Draw a character.
- ;
- ; Input:
- ; AL = character
- ; CX = screen width
- ; ES:DI = address to draw character at
- ;
- CharacterUp proc near
- push cx
- push si
- push di
- push ds
- ;
- ; Set DS:SI to point to font and ES to point to display memory.
- ;
- lds si,[FontPointer] ;point to font
- ;
- ; Calculate font address of character.
- ;
- mov bl,14 ;14 bytes per character
- mul bl
- add si,ax ;offset in font segment of character
-
- mov bp,FONT_CHARACTER_SIZE
- dec cx ; -1 because one byte per char
- CharacterLoop:
- lodsb ;get character byte
- mov ah,es:[di] ;load latches
- stosb ;write character byte
- ;
- ; Point to next line of character in display memory.
- ;
- add di,cx
- ;
- dec bp
- jnz CharacterLoop
- ;
- pop ds
- pop di
- pop si
- pop cx
- ret
- CharacterUp endp
- ;
- ; Set the pointer to the font to draw from to ES:BP.
- ;
- SelectFont proc near
- mov word ptr [FontPointer],bp ;save pointer
- mov word ptr [FontPointer+2],es
- ret
- SelectFont endp
- ;
- cseg ends
- end start
-